package cn.exrick.xboot.common.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static org.apache.commons.lang3.ObjectUtils.isNotEmpty;

/**
 *
 */
@Slf4j
public class BeanConvertUtils {
    /**
     * 方法说明：将bean转化为另一种bean实体
     * 
     * @param object
     * @param entityClass
     * @return
     */
    public static <T> T convertBean(Object object, Class<T> entityClass) {
        if(null == object) {
            return null;
        }
        return JSON.parseObject(JSON.toJSONString(object), entityClass);
    }


    /**
     * 方法说明：对象转换
     * 
     * @param source	原对象
     * @param target	目标对象
     * @param ignoreProperties	排除要copy的属性
     * @return
     */
    public static <T> T copy(Object source, Class<T> target, String...ignoreProperties){
        T targetInstance = null;
        try {
            targetInstance = target.getDeclaredConstructor().newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(ArrayUtils.isEmpty(ignoreProperties)) {
            BeanUtils.copyProperties(source, targetInstance);
        }else {
            BeanUtils.copyProperties(source, targetInstance, ignoreProperties);
        }
        return targetInstance;

    }

    /**
     * 方法说明：对象转换(List)
     * 
     * @param list	原对象
     * @param target	目标对象
     * @param ignoreProperties	排除要copy的属性
     * @return
     */
    public static <T, E> List<T> copyList(List<E> list, Class<T> target, String...ignoreProperties){
        List<T> targetList = new ArrayList<>();
        if(CollectionUtils.isEmpty(list)) {
            return targetList;
        }
        for(E e : list) {
            targetList.add(copy(e, target, ignoreProperties));
        }
        return targetList;
    }

    /**
     * 方法说明：map转化为对象
     * 
     * @param map
     * @param entityClass
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    public static <T> T mapToObject(Map<String, Object> map, Class<T> entityClass){
       return JSON.parseObject(JSON.toJSONString(map), entityClass);
    }

    /**
     * 方法说明：对象转化为Map
     * 
     * @param object
     * @return
     */
    public static Map objectToMap(Object object){
        return JSONObject.parseObject(JSON.toJSONStringWithDateFormat(object,"yyyy-MM-dd HH:mm:ss"));
    }

    /**
     * 对象转list
     * @param obj
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> List<T> castList(Object obj, Class<T> clazz)
    {
        List<T> result = new ArrayList<T>();
        if(obj instanceof List<?>)
        {
            for (Object o : (List<?>) obj)
            {
                result.add(clazz.cast(o));
            }
            return result;
        }
        return null;
    }
    /**
     * 判断对象是否为空
     * @param obj
     * @return
     */
    public static Boolean isNotEmptyBean(Object obj) {

        Boolean flag = false;

        try {
            if (null != obj){

                //得到类对象
                Class<?> c = (Class<?>) obj.getClass();

                //得到属性集合
                Field[] fs = c.getDeclaredFields();

                //得到方法体集合
                Method[] methods = c.getDeclaredMethods();

                //遍历属性

                for (Field f : fs) {

                    //设置属性是可以访问的(私有的也可以)
                    f.setAccessible(true);

                    String fieldGetName = parGetName(f.getName());

                    //判断属性是否存在get方法
                    if (!checkGetMet(methods, fieldGetName)) {
                        continue;
                    }

                    //得到此属性的值
                    Object val = f.get(obj);

                    //只要有1个属性不为空,那么就不是所有的属性值都为空
                    if (isNotEmpty(val)) {
                        flag = true;
                        break;
                    }
                }
            }
        } catch (Exception e) {
            log.error("判断对象是否为空出错：" + e.getMessage());
        }

        return flag;
    }
    /**
     * 拼接某属性的 get方法
     * @param fieldName
     * @return String
     */
    public static String parGetName(String fieldName) {
        if (null == fieldName || "".equals(fieldName)) {
            return null;
        }
        int startIndex = 0;
        if (fieldName.charAt(0) == '_')
            startIndex = 1;
        return "get"
                + fieldName.substring(startIndex, startIndex + 1).toUpperCase()
                + fieldName.substring(startIndex + 1);
    }

    /**
     * 判断是否存在某属性的 get方法
     * @param methods
     * @param fieldGetMet
     * @return boolean
     */
    public static Boolean checkGetMet(Method[] methods, String fieldGetMet) {

        for (Method met : methods) {
            if (fieldGetMet.equals(met.getName())) {
                return true;
            }
        }
        return false;
    }

}
